﻿using System;
using System.Collections.Generic;

namespace MetroNextTools.NBase
{
    public abstract class DisposableObject : SuspendableObject,IDisposable
    {
        #region Fields

        private bool disposed = false; //是否销毁

        #endregion

        #region Event

        private EventHandler disposingEvent;
        private EventHandler disposedEvent;

        public event EventHandler Disposing
        {
            add
            {
                this.disposingEvent = (EventHandler)Delegate.Combine(this.disposingEvent, value);
            }
            remove
            {
                this.disposingEvent = (EventHandler)Delegate.Remove(this.disposingEvent, value);
            }
        }

        public event EventHandler Disposed
        {
            add
            {
                this.disposedEvent = (EventHandler)Delegate.Combine(this.disposedEvent, value);
            }
            remove
            {
                this.disposedEvent = (EventHandler)Delegate.Remove(this.disposedEvent, value);
            }
        }

        #endregion

        ~DisposableObject()
        {
            DisposeCore(false);
        }

        public void Dispose()
        {
            this.DisposeCore(true);
            GC.SuppressFinalize(this);
        }

        /// <summary>
        /// 核心释放类
        /// 如果正在销毁则指释放托管资源
        /// </summary>
        /// <param name="disposing"></param>
        protected virtual void DisposeCore(bool disposing)
        {
            if (!disposed)
            {
                if (disposing)
                {
                    this.DisposeManagedResources();
                }
                this.DisposeUnManagedResources();
                disposed = true;
            }
        }

        /// <summary>
        /// 释放非托管资源
        /// </summary>
        protected virtual void DisposeUnManagedResources()
        {
            
        }

        /// <summary>
        /// 回收托管资源
        /// </summary>
        protected virtual void DisposeManagedResources()
        {
            List<Delegate> list = new List<Delegate>();
            this.CollectEvents(list);
            for (int i = 0; i < list.Count; i++)
            {
                Delegate @delegate = list[i];
                if (@delegate != null)
                {
                    Delegate[] invocationList = @delegate.GetInvocationList();
                    for (int j = 0; j < invocationList.Length; j++)
                    {
                        Delegate delegateInvocation = invocationList[j];
                        @delegate = Delegate.Remove(@delegate,delegateInvocation);
                    }
                }
            }
        }

        /// <summary>
        /// 回收托管的事件
        /// </summary>
        /// <param name="events"></param>
        protected virtual void CollectEvents(List<Delegate> events)
        {
            events.Add(this.disposingEvent);
            events.Add(this.disposedEvent);
        }
    }
}
